import re
import collections


NEWLINE_KEY = 'newline'
NEWLINE_REGX = r'(?P<newline>\n)'


class GrammerParse:

    '''
    语法解析
    '''

    def __init__(self):
        '''
        定义语法正则表达式，默认为空
        '''
        self.line_num = 0
        self.column_num = 0
        self.line_start = 0
        self.grammer_list = self.get_grammer_list()
        if self.grammer_list is None:
            return
        self.grammer_list.append(NEWLINE_REGX)
        self.grammer_regx = re.compile('|'.join(self.grammer_list))

    def get_grammer_list(self):
        '''
        返回语法列表，默认为None
        ,需要子类实现
        '''
        return None

    def parse_item(self, match, file_path):
        ''''
        解析每一项语法，返回识别项
        需要子类实现
        '''
        return None

    def valid(self):
        '''
        判断语法解析器是否完整，
        当self.grammer_regx定义后，表明语法解析可用
        '''
        return self.grammer_regx is not None

    def read_content(self, file_path):
        """
        读取并返回文件内容
        """
        content_list = None
        with open(file_path, 'r', encoding='utf-8') as f:
            content_list = f.readlines()
        return ''.join(content_list)

    def format_result(self, data):
        '''
        对解析的数据列表格式化处理
        需要子类实现
        '''

    def parse(self, *file_paths):
        '''
        执行解析，返回解析结果列表
        '''
        if not self.valid():
            raise Exception('Please initial self.grammer_regx!!')
        result = []
        for path in file_paths:
            content = self.read_content(path)
            self.line_num = 1
            self.column_num = 0
            self.line_start = 0
            result_item = []
            for match in self.grammer_regx.finditer(content):
                rank = match.lastgroup
                if(rank == NEWLINE_KEY):
                    pos_end = match.end(rank)
                    self.line_num += 1
                    self.line_start = pos_end
                    continue
                else:
                    item = self.parse_item(match, path)
                    if item is not None:
                        result_item.append(item)
            self.format_result(result_item)
            result.extend(result_item)
        return result


class MarkdownParse(GrammerParse):
    '''
    markdown解析
    '''
    RANK_KEY = 'rank'
    VALUE_KEY = 'value'

    Field = collections.namedtuple(
        'Field', ['rank', 'value', 'line', 'column', 'file_path'])

    def get_grammer_list(self):
        return [
            r'(?P<rank>#+)\s+(?P<value>.*)',
        ]

    def parse_item(self, match, file_path):
        rank = match[self.RANK_KEY]
        value = match[self.VALUE_KEY]
        self.column_num = match.start(self.VALUE_KEY)-self.line_start
        item = self.Field(rank, value, self.line_num,
                          self.column_num, file_path)._asdict()
        temp = re.findall(NEWLINE_REGX, value)
        self.line_num += len(temp)
        if len(temp) > 0:
            self.line_start = match.end(rank)-len(temp[0])
        return item

    def format_result(self, data):
        rank_regx = re.compile(r'#')
        for section in data:
            rank = len(rank_regx.findall(section['rank']))
            section['rank'] = "  "*rank + str(rank)


def test_markdown(file_path):
    '''
    测试解析
    '''
    data = MarkdownParse().parse(file_path)
    line = ['{line:3}:{column:<3} {rank:4} {value}'.format_map(item)
            for item in data]
    print('\n'.join(line))


#  file_path = '/Users/liluyue/note/essay/algorithm.md'
#  test_markdown(file_path)
